
#include <errno.h>
#include <signal.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/un.h>
#include <assert.h>
#include <sys/socket.h>
#include "sock_pool.h"
#include <arpa/inet.h>
#include "../main.h"




//#define DEBUG_EN

#ifdef DEBUG_EN
	#ifndef DEBUG_EN_SPEC
	#define DEBUG_EN_SPEC		// FIXME
	#endif
#endif


static sock_deal_packed		m_pdeal		= NULL;

/************************************************************************************
 * The const variables and macros
 *  svr : server
 *  clt : client
 ************************************************************************************/
static const struct
{
	int						g_tcp_svr_port;
	int						g_udp_svr_port;
	int						keeplive;
}	g_so_def_val	=
	{
		4000, 4001, 10, 
	};

static const char			* g_so_un_name_svr	= "/tmp/un_so_svr";
/*static const char			* g_so_un_name_clt	= "/tmp/un_so_clt";*/

static int					g_tcp_svr_port;
static int					g_udp_svr_port;
static int					g_tcp_keeplive;

static int					g_fd_svr_unx		= -1;
static int					g_fd_svr_tcp 		= -1;
static int					g_fd_svr_udp		= -1;

static const time_t			g_fdi_idle_time		= 60;	// 60sec

inline int					fdi2ind( int fdi )	{ return (fdi + 1); }
inline int					ind2fdi( int ind )	{ return (ind - 1); }


/*************************************************************************************/
fdi_list::fdi_list( int max ) : m_max( max ), m_lst( max, 1 )
{
	assert( max <= SOCK_MAX_NUM );

	fd_info_t		fdi;

	m_num			= 0;
	for( int i = 0; i < m_max; i++ )
	{
		fdi.fd		= -1;
		fdi.addr	= 0;
		fdi.port	= 0;
		fdi.timer	= 0;

		m_lst.append( fdi );
	}
}

int fdi_list::insert( fd_info_t * fdi )
{
	int				i, idle;

	if( fdi == NULL )
	{
		return -1;
	}

	for( i = 0, idle = -1; i < m_num; i++ )
	{
		if( m_lst[i].fd == fdi->fd && m_lst[i].addr == fdi->addr && m_lst[i].port == fdi->port )
		{
			time( &m_lst[i].timer );

			return i;
		}

		if( idle == -1 )
		{
			idle	= i;

		}
	}

	if( idle != -1 )
	{
		m_lst[idle].fd		= fdi->fd;
		m_lst[idle].addr	= fdi->addr;
		m_lst[idle].port	= fdi->port;
		time( &m_lst[idle].timer );

		return idle;
	}
	else if( m_num < m_max )
	{
		m_lst[m_num].fd		= fdi->fd;
		m_lst[m_num].addr	= fdi->addr;
		m_lst[m_num].port	= fdi->port;
		time( &m_lst[m_num].timer );
		
		m_num++;
		return m_num - 1;
	}

#ifdef DEBUG_EN_SPEC
	printf( "\tCan't insert the frame into the frame number list idle = %d, m_num = %d, m_max = %d !!!\n", idle, m_num, m_max );
#endif

	return -2;
}

void fdi_list::remove( int fd )
{
	int				i;

	for( i = 0; i < m_num; i++ )
	{
		if( m_lst[i].fd == fd )
		{
			m_lst[i].fd	= -1;
		}
	}

	for( i = m_num - 1; i >= 0; i-- )
	{
		if( m_lst[i].fd != -1 )
		{
			m_num	= i + 1;
			return;
		}
	}
}

int fdi_list::get( int ind, fd_info_t * fdi )
{
	if( ind < 0 || ind >= m_num )
		return -1;

	if( m_lst[ind].fd == -1 )
		return -2;

	*fdi	= m_lst[ind];

	return 0;
}

void fdi_list::tick( void )
{
	int				i;
	time_t			cur_time;

	for( i = 0; i < m_num; i++ )
	{

		if( m_lst[i].fd != -1 )
		{
			time( &cur_time );

			if( cur_time - m_lst[i].timer >= g_fdi_idle_time )
			{
#ifdef DEBUG_EN_SPEC
				printf( "\nfdi_list_tick timeout fd = %d i = %d max[%d] !!!\n", m_lst[i].fd, i, m_num );
#endif
				m_lst[i].fd	= -1;
			}
		}
	}
}

void fdi_list::show( void )
{
	int				i;

	for( i = 0; i < m_num; i++ )
	{
		if( m_lst[i].fd != -1 )
		{
#ifdef DEBUG_EN_SPEC
			printf( "fdi_list %d = %d %d %x\n", i, m_lst[i].fd, m_lst[i].port, (int)m_lst[i].timer );
#endif
		}
	}
}


fd_table::fd_table( void )
{
	m_num				= 0;
	for( int i = 0; i < FD_POOLMAX_NUM; i++ )
	{
		m_lst[i].fd		= -1;

		m_lst[i].len	= 0;
		m_lst[i].prx	= NULL;
	}
}

int fd_table::insert( int fd, int has_buf )
{
	if( fd >= FD_POOLMAX_NUM || fd < 0 )
		return -1;

	if( m_lst[fd].fd != -1 || (has_buf && m_lst[fd].prx != NULL) )
		return -2;

	if( has_buf )
	{
		m_lst[fd].len	= 0;
		m_lst[fd].prx	= new unsigned char [ FD_BUF_SIZE ];
		if( m_lst[fd].prx == NULL )
			return -3;
	}
	else if( m_lst[fd].prx != NULL )
	{
		delete [] m_lst[fd].prx;
		m_lst[fd].prx	= NULL;
	}

	m_lst[fd].fd	= fd;

	if( fd >= m_num )
	{
		m_num		= fd + 1;
	}

	return fd;
}

void fd_table::remove( int fd )
{
	if( fd >= m_num || fd < 0 )
		return;

	if( m_lst[fd].prx != NULL )
	{
		delete [] m_lst[fd].prx;
	}
	m_lst[fd].len	= 0;
	m_lst[fd].prx	= NULL;
	m_lst[fd].fd	= -1;

	for( int i = m_num - 1; i >= 0; i-- )
	{
		if( m_lst[i].fd != -1 )
		{
			m_num	= i + 1;
			return;
		}
	}
}

unsigned char * fd_table::get( int fd )
{
	if( fd >= m_num || fd < 0 )
		return NULL;

	return m_lst[fd].prx;
}

sock_pool * sock_pool::m_pthis	= NULL;
sock_pool::sock_pool( int max ) : m_max(max)
{
	m_tbl	= new fd_table( );
	m_fdi	= new fdi_list( m_max );
	create_svr( );
}

sock_pool::~sock_pool( void )
{
	so_delete( );

}

sock_pool * sock_pool::instance( int max )
{
	if( m_pthis == NULL )
	{
		m_pthis		= new sock_pool( max );
	}

	return m_pthis;
}

void sock_pool::free( void )
{
	if( m_pthis != NULL )
	{
		delete m_pthis;
	}

	m_pthis			= NULL;
}

void sock_pool::re_create( void )
{
	for( int i = 0; i < m_tbl->m_num; i++ )
	{
		if( m_tbl->m_lst[i].fd < 0 )
			continue;

		fd_close( i );
	}
	delete m_fdi;
	delete m_tbl;

	m_tbl	= new fd_table( );
	m_fdi	= new fdi_list( m_max );
	create_svr( );
}

void sock_pool::so_delete( void )
{
	for( int i = 0; i < m_tbl->m_num; i++ )
	{
		if( m_tbl->m_lst[i].fd < 0 )
			continue;

		fd_close( i );
	}
	delete m_fdi;
	delete m_tbl;
}

void sock_pool::tick( sock_deal_packed func )
{
	int						fd;
	int						i;
	int						rc;
	fd_set					fs_rd;
	struct timeval			tvwait;

	// 
	m_pdeal		= func;

	m_fdi->tick( );	

	/* FD_ZERO */
	FD_ZERO( &fs_rd );
    /* FD_SET the client server */
	for( i = 0; i < m_tbl->m_num; i++ )
	{
		if( m_tbl->m_lst[i].fd >= 0 )
		{
			fd  = i;
			FD_SET( fd, &fs_rd );
			
		}
	}

	/* select, don't wait at all */
	tvwait.tv_sec	= 0;
#ifdef PC_SIMULATE
	tvwait.tv_usec	= 1;
#else
	tvwait.tv_usec	= 0;
#endif

	if( select( m_tbl->m_num, &fs_rd, NULL, NULL, &tvwait ) <= 0 )
	{
		return;
	}

	/* check */
	for( i = 0; i < m_tbl->m_num; i++ )
	{
		if( m_tbl->m_lst[i].fd < 0 )
			continue;

		fd  = i;
		/* read */
		if( FD_ISSET( fd, &fs_rd ) )
		{
			if( fd == g_fd_svr_tcp || fd == g_fd_svr_unx )
			{
				if( fd == g_fd_svr_tcp )
				{
					fd = so_accept_tcp( fd );
#ifdef DEBUG_EN_SPEC
					if(fd > 0)
					{
						printf("####the connect fd :%d\n",fd);
					}
#endif
				}
				else
				{
					fd = so_accept_unx( fd, NULL );
				}

				if( fd > 0 )
				{
#ifdef DEBUG_EN_SPEC
					struct sockaddr_in		addr;
					socklen_t				addr_len;

					if( getpeername( fd, (struct sockaddr *)&addr, &addr_len ) >= 0 )
					{
						printf( "\nThe server fd = %d, new fd = %d ,client info:addr[0x%08X],port [%d]\n", i, fd, addr.sin_addr.s_addr, addr.sin_port );
					}
					else
					{
						printf( "\nThe server fd = %d, i = %d accept !\n", fd, i );
					}
#endif
					
					/* insert it into the fd_list */
					rc  = m_tbl->insert( fd, 1 );
					/* insert failed */
					if( rc < 0 )
					{
#ifdef DEBUG_EN_SPEC
						printf( "\tCan't insert the client into the list rc = %d !!!\n", rc );
#endif
						close( fd );
					}
				}
				else
				{
#ifdef DEBUG_EN_SPEC
					printf( "\n Can't accept fd = %d, err = %d !\n", fd, errno );
#endif
				}
			}
			else
			{
				/* read the data */
				if( fd == g_fd_svr_udp )
				{
					fd_rx_dgram( fd );
				}
				else
				{
					fd_rx_stream( fd );
				}
			}
		}
	}
}
#if 0
int sock_pool::fd_send( int ind, unsigned char * pdata, int len )
{
	int						fd = -1;
	int						rc;
	int						i;
	struct sockaddr_in		addr;
	socklen_t				addr_len;
	fd_info_t				fdi;

	if( pdata == NULL || ind < 0 )
	{
		return -2;
	}

	/* broadcast */
    if( ind == 0 )
    {
#ifdef DEBUG_EN_SPEC
		printf( "\nsend a broadcast frame len = %d \n", len );
#endif

/*		// udp broadcast
		fdi.fd					= g_fd_svr_udp;
		fdi.port				= g_udp_svr_port;
		fdi.addr				= INADDR_BROADCAST;

		addr.sin_family			= AF_INET;
		addr.sin_port			= htons( fdi.port );
		addr.sin_addr.s_addr	= htonl( fdi.addr );
		bzero( &addr.sin_zero, 8 );
		addr_len				= sizeof( addr );

		if( (rc  = sendto( fdi.fd, pdata, len, 0, (struct sockaddr *)&addr, addr_len )) < 0 )
		{
			// close it
#ifdef DEBUG_EN_SPEC
			printf( "\n\t\tsend error fd = %d", fdi.fd );
#endif
		}
*/
    	/* tcp broadcast */
		for( i = 0; i < m_tbl->m_num; i++ )
		{
			fd		= m_tbl->m_lst[i].fd;
			if( fd < 0 || fd == g_fd_svr_tcp || fd == g_fd_svr_udp || fd == g_fd_svr_unx )
				continue;

			fdi.fd	= i;
			if( (rc = send( fdi.fd, pdata, len, 0 )) < 0 )
			{
				/* close it */
				fd_close( fdi.fd );
#ifdef DEBUG_EN_SPEC
				printf( "\n\t\tsend error, close it fd = %d ", fdi.fd );
#endif
			}
		}
    }
	else
	{
		i		= ind2fdi( ind );
		if( 0 != m_fdi->get( i, &fdi ) )
			return 0;

		fd		= m_tbl->m_lst[fdi.fd].fd;
		if( fd != g_fd_svr_tcp && fd != g_fd_svr_unx )
		{
			if( fdi.fd == g_fd_svr_udp )
			{
				addr.sin_family			= AF_INET;
				addr.sin_port			= htons( fdi.port );
				addr.sin_addr.s_addr	= htonl( fdi.addr );
				memset( &addr.sin_zero,0, 8 );//fixed by hqq
				addr_len				= sizeof( addr );

#ifdef DEBUG_EN_SPEC
				printf( "\nsend a UDP frame len = %d to fd = %d [0x%08X:%d]\n", len, fdi.fd, fdi.addr, fdi.port );
#endif
				if( (rc  = sendto( fdi.fd, pdata, len, 0, (struct sockaddr *)&addr, addr_len )) < 0 )
				{
#ifdef DEBUG_EN_SPEC
					printf( "\n\t\tsend error fd = %d", fdi.fd );
#endif
				}
    		}
			else
			{
#ifdef DEBUG_EN_SPEC
			    printf( "\nsend a TCP frame len = %d to fd = %d [0x%08X:%d]\n", len, fdi.fd, fdi.addr, fdi.port );
#endif

				if( (rc = send( fdi.fd, pdata, len, 0 )) < 0 )
				{
					fd_close( fdi.fd );
#ifdef DEBUG_EN_SPEC
					printf( "\n\t\tsend error, close it fd = %d ", fdi.fd );
#endif
				}
			}
		}
	}

	return 0;
}
#endif


int sock_pool::fd_send(int ind, unsigned char * pdata, int len )
{
	int						fd = -1;
	int						rc = 0;
	//struct sockaddr_in		addr;
	//socklen_t				addr_len;
	fd_info_t				fdi;

	if( pdata == NULL)
	{
		return -2;
	}
	
	for(int i=0; i < m_tbl->m_num;i++)
	{
#ifdef DEBUG_EN_SPEC
		printf("[%d]fd:%d\n", i, m_tbl->m_lst[i].fd);
#endif
		if(m_tbl->m_lst[i].fd > 0)
		{

			fd = m_tbl->m_lst[i].fd ;
			fdi.fd = fd;
		}
	}
#ifdef DEBUG_EN_SPEC
	printf("fd = %d\n",fd);
#endif

	if( (fd != g_fd_svr_tcp) && (fd != g_fd_svr_unx) && (fd != g_fd_svr_udp) )
	{
#ifdef DEBUG_EN_SPEC
		printf("###fdi.fd == %d\n",fdi.fd);
#endif
#if 0
		if( fdi.fd == g_fd_svr_udp )
		{
			addr.sin_family			= AF_INET;
			addr.sin_port			= htons( fdi.port );
			addr.sin_addr.s_addr	= htonl( fdi.addr );
			memset( &addr.sin_zero,0, 8 );//fixed by hqq
			addr_len				= sizeof( addr );

#ifdef DEBUG_EN_SPEC
			printf( "\nsend a UDP frame len = %d to fd = %d [0x%08X:%d]\n", len, fdi.fd, fdi.addr, fdi.port );
#endif
			if( (rc  = sendto( fdi.fd, pdata, len, 0, (struct sockaddr *)&addr, addr_len )) < 0 )
			{
#ifdef DEBUG_EN_SPEC
				printf( "\n\t\tsend error fd = %d", fdi.fd );
#endif
			}
		}
		else
#endif
		{
#ifdef DEBUG_EN_SPEC_PRINT_FRAM
		    printf( "\n############send a TCP frame len = %d to fd = %d [0x%08X:%d]\n", len, fdi.fd, fdi.addr, fdi.port );

			printf("\n############send start:\n");
			for(int j = 0;j < len;j++)
			{
				printf("%02x ",pdata[j]);
			}
			printf("\n############send end\n");
#endif

			if( (rc = send( fdi.fd, pdata, len, 0 )) < 0 )
			{
				fd_close( fdi.fd );
#ifdef DEBUG_EN_SPEC
				printf( "\n\t\tsend error, close it fd = %d ", fdi.fd );
#endif
			}
		}
	}

	//return 0;
	return rc;
}

void sock_pool::create_svr( void )
{
	int						fd;
	unsigned int			i;
	unsigned char			err;
	struct sockaddr_un		unx_addr;
	struct sockaddr_in		tcp_addr;
	struct sockaddr_in		udp_addr;
	int						unx_len;
	int						tcp_len;
	int						udp_len;
	struct
	{
		int *				pfd;
		int					type;
		struct sockaddr *	paddr;
		int *				plen;
		int					clt_num;
		int					has_buf;
	}	svr_info[]	= 	{
							{ &g_fd_svr_tcp, SOCK_STREAM, (struct sockaddr *)&tcp_addr, &tcp_len, SO_TCP_MAX_NUM, 0 },
							{ &g_fd_svr_udp, SOCK_DGRAM , (struct sockaddr *)&udp_addr, &udp_len, SO_UDP_MAX_NUM, 1 },
							{ &g_fd_svr_unx, SOCK_STREAM, (struct sockaddr *)&unx_addr, &unx_len, SO_UNX_MAX_NUM, 0 }
						};

	// ignore sigpipe
	signal( SIGPIPE, SIG_IGN );

	fd_init( );

	/* init the tcp server info. */
	tcp_addr.sin_family			= AF_INET;
	tcp_addr.sin_port			= htons( g_tcp_svr_port );
	tcp_addr.sin_addr.s_addr	= htonl( INADDR_ANY );
	memset( &tcp_addr.sin_zero,0, 8 );//fixed by hqq
	tcp_len						= sizeof( tcp_addr );

	/* init the udp server info. */
	udp_addr.sin_family			= AF_INET;
	udp_addr.sin_port			= htons( g_udp_svr_port );
	udp_addr.sin_addr.s_addr	= htonl( INADDR_ANY );
	memset( &udp_addr.sin_zero,0, 8 );//fixed by hqq
	udp_len						= sizeof( udp_addr );

	/* init the the unix server info. */
	unlink( g_so_un_name_svr );				// if the file already exits, delete it
	memset( &unx_addr, 0, sizeof(unx_addr) );
	unx_addr.sun_family			= AF_UNIX;
	strcpy( unx_addr.sun_path, g_so_un_name_svr );
	unx_len						= offsetof( struct sockaddr_un, sun_path ) + strlen( g_so_un_name_svr );

	/* create servers */
	for( i = 0; i < sizeof(svr_info)/sizeof(svr_info[0]); i++ )
	{
		fd						= so_server_create( svr_info[i].type, svr_info[i].paddr, *svr_info[i].plen, svr_info[i].clt_num );
		if( fd < 0 )
		{
			*svr_info[i].pfd	= -1;
			err					|= (0x01 << i);
#ifdef DEBUG_EN_SPEC
			printf( "\ncreate the %d socket server failed fd = %d errno = %d \n", i, fd, errno );
			printf( "\ttype : %d, len : %d clt_num : %d \n", svr_info[i].type, *svr_info[i].plen, svr_info[i].clt_num );
#endif
		}
		else
		{
#ifdef DEBUG_EN_SPEC
			printf( "\ncreate the %d socket server OK : fd = %d \n", i, fd );
			printf( "\ttype : %d, len : %d clt_num : %d \n", svr_info[i].type, *svr_info[i].plen, svr_info[i].clt_num );
#endif
			*svr_info[i].pfd	= fd;
			m_tbl->insert( fd, svr_info[i].has_buf );
		}
	}
}

void sock_pool::fd_init( void )
{
	g_tcp_svr_port	= g_so_def_val.g_tcp_svr_port;
	g_udp_svr_port	= g_so_def_val.g_udp_svr_port;
	g_tcp_keeplive	= g_so_def_val.keeplive;

	g_fd_svr_tcp	= -1;
	g_fd_svr_udp	= -1;
	g_fd_svr_unx	= -1;
}

void sock_pool::fd_close( int fd )
{
    close( fd );

	m_tbl->remove( fd );
	m_fdi->remove( fd );
}

void sock_pool::fd_rx_stream( int fd )
{
	int         			rc;
	int						len;
	int						clr;
	unsigned char *			prs;
	unsigned char *			phead;
	struct sockaddr_in		addr;
	socklen_t				addr_len;
	fd_info_t 				fdi;

	prs		= m_tbl->get( fd );
	if( prs == NULL )
    {
#ifdef DEBUG_EN_SPEC
    	printf( "%s", "\tthe buffer is NULL\n" );
#endif
    	return;
   	}

	len		= m_tbl->m_lst[fd].len;
	
	rc		= recv( fd, prs + len, FD_BUF_SIZE - len, 0 );

	if( rc > 0 )
	{
#ifdef DEBUG_EN_SPEC
		printf( "fd[%d] receive len = %d data\n", fd, rc );
		for(int i=0;i<rc;i++)
		{

			if(i%8 == 0)
				printf("\n");
			
				printf("%02X ",(prs + len)[i]);
		}
		printf("\n");

#endif

		len			+= rc;
		clr			= 1;
		addr_len	= sizeof( addr );

		if( getpeername( fd, (struct sockaddr *)&addr, &addr_len ) >= 0 )
		{
			fdi.fd		= fd;
			fdi.addr	= ntohl( addr.sin_addr.s_addr );
			fdi.port	= ntohs( addr.sin_port );

			if( (rc = m_fdi->insert( &fdi )) >= 0 )
			{
				if( m_pdeal != NULL )
				{
					if( (phead = m_pdeal( fdi2ind( rc ), prs, len, 0 )) != NULL )
					{
						if( phead != prs )
						{
							len		-= phead - prs;
							memmove( prs, phead, len );

							clr		= 0;
						}
					}
				}
			}
		}
#ifdef DEBUG_EN_SPEC
		else
		{
			printf( "%s", "\n\t\tgetpeername error!\n" );
		}
#endif

		if( clr )
		{
			len					= 0;
		}
		m_tbl->m_lst[fd].len	= len;
    }
    else
    {
#ifdef DEBUG_EN_SPEC
        printf( "\n\tThe client fd = %d CLOSE !\n", fd );
#endif
	    fd_close( fd );
    }
}

void sock_pool::fd_rx_dgram( int fd )
{
	int         			rc;
	int						len;
	unsigned char *			prs;
	struct sockaddr_in		addr;
	socklen_t				addr_len;
	fd_info_t				fdi;

	prs		= m_tbl->get( fd );
    if( prs == NULL )
    {
#ifdef DEBUG_EN_SPEC
    	printf( "%s", "\tthe buffer is NULL\n" );
#endif
    	return;
   	}

	addr.sin_family			= AF_INET;
	addr.sin_port			= htons( g_udp_svr_port );
	addr.sin_addr.s_addr	= htonl( INADDR_ANY );
	memset( &addr.sin_zero,0, 8 );//fixed by hqq
	addr_len				= sizeof( addr );

	if( (len  = recvfrom( fd, prs, FD_BUF_SIZE, 0, (struct sockaddr *)&addr, &addr_len )) > 0 )
	{
		fdi.fd				= fd;
		fdi.addr			= ntohl( addr.sin_addr.s_addr );
		fdi.port			= ntohs( addr.sin_port );

		if( (rc = m_fdi->insert( &fdi )) >= 0 )
		{
#ifdef DEBUG_EN_SPEC
			printf( "\n\tfd_rx_dgram receive len = %d, [0x%08x:%d]\n", len, fdi.addr, fdi.port );
#endif

			if( m_pdeal != NULL )
			{
				m_pdeal( fdi2ind( rc ), prs, len, 1 );
			}
	    }
	}
}

int sock_pool::so_server_create( int type, const struct sockaddr * addr, socklen_t alen, int clt_num )
{
	int			fd;
	int			err;
	int			ret		= 0;
	int			reuse	= 1;

	if( (fd = socket( addr->sa_family, type, 0 )) < 0 )
		return -1;

	if( addr->sa_family == AF_INET	)
	{
		if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int) ) < 0 )
		{
			ret		= -2;
			goto so_svr_create_err;
		}
	}

	if( bind( fd, addr, alen ) < 0 )
	{
		ret			= -3;
		goto so_svr_create_err;
	}

	if( type == SOCK_STREAM || type == SOCK_SEQPACKET )
	{
		if( listen( fd, clt_num ) < 0 )
		{
			ret		= -4;
			goto so_svr_create_err;
		}
	}

	return fd;

so_svr_create_err:
	err 	= errno;
	close( fd );
	errno	= err;

	return ret;
}

int sock_pool::so_accept_unx( int svr_fd, char * pcltname )
{
	int						fd;
	int						len;
	struct sockaddr_un		addr;
	struct timeval			tm_arg;

	len		= sizeof(addr);
	if( (fd = accept( svr_fd, (struct sockaddr *)&addr, (socklen_t *)(&len) )) < 0 )
		return -1;

	tm_arg.tv_sec	= 1;
	tm_arg.tv_usec	= 0;
	if( setsockopt( fd, SOL_SOCKET, SO_SNDTIMEO, &tm_arg, sizeof(tm_arg) ) < 0 )
	{
		close( fd );
		return -2;
	}

	len		-= offsetof( struct sockaddr_un, sun_path );
	addr.sun_path[len]	= '\0';
	if( pcltname != NULL )
	{
	    strcpy( pcltname, addr.sun_path );
	}

	return fd;
}

int sock_pool::so_accept_tcp( int svr_fd )
{
	int						fd;
	int						len;
	int						err;
	int						ret;
	int                     opt_arg;
	struct sockaddr_in		addr;
	struct timeval			tm_arg;

	len		= sizeof(addr);
	if( (fd = accept( svr_fd, (struct sockaddr *)&addr, (socklen_t *)(&len) )) < 0 )
		return -1;

	// set the send_buff size and the receive_buff size
/*	
	opt_arg		= 6144;
	if( setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &opt_arg, sizeof(opt_arg) ) < 0 )
	{
		ret		= -2;
		goto so_accept_tcp_err;
	}

	opt_arg		= 6144;
	if( setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &opt_arg, sizeof(opt_arg) ) < 0 )
	{
		ret		= -3;
		goto so_accept_tcp_err;
	}
*/

	/* set the keepalive option */
	opt_arg		= 1;
	if( setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &opt_arg, sizeof(opt_arg) ) < 0 )
	{
		ret		= -4;
		goto so_accept_tcp_err;
	}

	/* set option */
	tm_arg.tv_sec	= 1;
	tm_arg.tv_usec	= 0;
	if( setsockopt( fd, SOL_SOCKET, SO_SNDTIMEO, &tm_arg, sizeof(tm_arg) ) < 0 )
	{
		ret		= -5;
		goto so_accept_tcp_err;
	}

	return fd;

so_accept_tcp_err:
	err		= errno;
	close( fd );
	errno	= err;

	return ret;
}

